from django.contrib import admin  
from django.db.models import Q  
from django.utils.translation import gettext as _  
from django.http import JsonResponse, HttpResponse  
from django.urls import path, reverse  
from django.db import transaction  
from django.contrib.admin.models import LogEntry  
from django.contrib.contenttypes.models import ContentType  
from simpleui.admin import AjaxAdmin  
from import_export import resources  
from import_export.admin import ImportExportActionModelAdmin  
import json  
import io  
import xlsxwriter  
from .models import *
  
class MaterialInfoResource(resources.ModelResource):  
    class Meta:  
        model = MaterialInfo  
        fields = ('salesperson', 'original_pn', 'fab_pn', 'new_pn', 'status',   
                 'customer', 'machine_model', 'category', 'department', 'oem',  
                 'product_info', 'size_standard', 'size', 'pcs_per_chamber',  
                 'original_usage', 'material', 'current_material', 'current_supplier',  
                 'usage_cycle', 'replacement_material', 'currency', 'unit_price')  
  
@admin.register(MaterialInfo)  
class MaterialInfoAdmin(AjaxAdmin, ImportExportActionModelAdmin):  
    resource_class = MaterialInfoResource  
      
    # 管理员完整字段  
    ADMIN_LIST_DISPLAY = (  
        'salesperson', 'original_pn', 'fab_pn', 'new_pn', 'status',  
        'customer', 'machine_model', 'category', 'department', 'oem',  
        'product_info', 'size_standard', 'size', 'pcs_per_chamber', 'original_usage',  
        'material', 'current_material', 'current_supplier', 'usage_cycle',   
        'replacement_material', 'currency', 'unit_price'  
    )  
      
    # 普通用户字段（排除敏感信息）  
    USER_LIST_DISPLAY = tuple(field for field in ADMIN_LIST_DISPLAY   
                            if field not in ['new_pn', 'salesperson'])  
      
    def get_list_display(self, request):  
        if request.user.is_superuser:  
            return self.ADMIN_LIST_DISPLAY  
        return self.USER_LIST_DISPLAY  
      
    # 搜索字段配置  
    ADMIN_SEARCH_FIELDS = ('original_pn', 'fab_pn', 'new_pn', 'customer', 'machine_model')  
    USER_SEARCH_FIELDS = ('original_pn',)  
      
    def get_search_fields(self, request):  
        if request.user.is_superuser:  
            return self.ADMIN_SEARCH_FIELDS  
        return self.USER_SEARCH_FIELDS  
      
    list_display_links = ('original_pn',)  
    date_hierarchy = 'created_at'  
    ordering = ['original_pn']  
    list_per_page = 20  
    actions_on_top = True  
    change_list_template = 'admin/material_change_list.html'  
      
    # 自定义动作  
    actions = ['multi_search_action', 'export_selected', 'add_to_cart',   
               'export_cart', 'single_export', 'view_user_logs']  
      
    # 功能1：多料号精准搜索 - 关键修正  
    def multi_search_action(self, request, queryset):  
        """多料号搜索动作"""  
        # 检查是否有弹出层提交的数据  
        part_numbers = request.POST.get('part_numbers', '').strip()  
          
        if part_numbers:  
            # 处理提交的料号数据  
            pn_list = [pn.strip() for pn in part_numbers.split('\n') if pn.strip()]  
              
            # 构建重定向URL  
            opts = self.model._meta  
            redirect_url = reverse(f'admin:{opts.app_label}_{opts.model_name}_changelist')  
              
            # 添加搜索参数  
            if pn_list:  
                search_query = '|'.join(pn_list)  
                redirect_url += f'?q={search_query}'  
              
            return JsonResponse({  
                'status': 'redirect',  
                'url': redirect_url  
            })  
        else:  
            # 没有数据时返回成功，让 SimpleUI 显示弹出层  
            return JsonResponse({  
                'status': 'success',  
                'msg': '请在弹出层中输入要搜索的料号'  
            })  
      
    def multi_search_layer(self, request):  
        """多料号搜索弹出层配置 - 关键修正：返回正确的数据结构"""  
        return {  
            'layer': {  # 注意：这里需要包装在 'layer' 键中  
                'title': '多料号精准搜索',  
                'width': '600px',  
                'labelWidth': '150px',  
                'params': [  
                    {  
                        'type': 'textarea',  
                        'key': 'part_numbers',  
                        'label': '原厂料号（每行一个）',  
                        'require': True,  
                        'width': '100%',  
                        'size': 'small',  
                        'placeholder': '请输入料号，每行一个\n例如：\nPN001\nPN002\nPN003'  
                    }  
                ],  
                'confirm_button': '搜索',  
                'cancel_button': '取消'  
            }  
        }  
      
    # 关联弹出层到动作 - 这是关键步骤  
    multi_search_action.layer = multi_search_layer  
    multi_search_action.short_description = '多料号精准搜索'  
    multi_search_action.icon = 'el-icon-search'  
      
    # 重写搜索逻辑以支持多料号搜索  
    def get_search_results(self, request, queryset, search_term):  
        """重写搜索逻辑支持多料号搜索"""  
        if '|' in search_term:  
            # 处理多料号搜索  
            pn_list = [pn.strip() for pn in search_term.split('|') if pn.strip()]  
            q_objects = Q()  
            for pn in pn_list:  
                q_objects |= Q(original_pn__exact=pn)  # 精准匹配  
              
            queryset = queryset.filter(q_objects)  
            use_distinct = False  
        else:  
            # 使用默认搜索  
            queryset, use_distinct = super().get_search_results(request, queryset, search_term)  
          
        return queryset, use_distinct  
      
    # 其他功能保持不变...  
    def add_to_cart(self, request, queryset):  
        """添加到购物车"""  
        cart_items = request.session.get('material_cart', [])  
          
        for obj in queryset:  
            if obj.id not in cart_items:  
                cart_items.append(obj.id)  
          
        request.session['material_cart'] = cart_items  
          
        return JsonResponse({  
            'status': 'success',  
            'msg': f'已添加 {queryset.count()} 项到购物车，购物车共 {len(cart_items)} 项'  
        })  
      
    add_to_cart.short_description = '添加到购物车'  
    add_to_cart.icon = 'el-icon-shopping-cart-2'  
      
    def export_selected(self, request, queryset):  
        """导出选中的数据"""  
        if not request.user.is_superuser and queryset.count() > 100:  
            return JsonResponse({  
                'status': 'error',  
                'msg': '普通用户单次导出不能超过100条记录'  
            })  
          
        return self._export_to_excel(queryset, '选中数据导出')  
      
    export_selected.short_description = '导出选中数据'  
    export_selected.icon = 'el-icon-download'  
      
    def _export_to_excel(self, queryset, filename):  
        """通用Excel导出方法"""  
        output = io.BytesIO()  
        workbook = xlsxwriter.Workbook(output)  
        worksheet = workbook.add_worksheet()  
          
        # 根据用户权限确定导出字段  
        if request.user.is_superuser:  
            fields = self.ADMIN_LIST_DISPLAY  
        else:  
            fields = self.USER_LIST_DISPLAY  
          
        # 写入表头  
        headers = []  
        for field in fields:  
            try:  
                verbose_name = MaterialInfo._meta.get_field(field).verbose_name  
                headers.append(verbose_name)  
            except:  
                headers.append(field)  
          
        for col, header in enumerate(headers):  
            worksheet.write(0, col, header)  
          
        # 写入数据  
        for row, obj in enumerate(queryset, 1):  
            for col, field in enumerate(fields):  
                value = getattr(obj, field, '')  
                if hasattr(value, 'strftime'):  
                    value = value.strftime('%Y-%m-%d %H:%M:%S')  
                worksheet.write(row, col, str(value))  
          
        workbook.close()  
        output.seek(0)  
          
        response = HttpResponse(  
            output.read(),  
            content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'  
        )  
        response['Content-Disposition'] = f'attachment; filename="{filename}.xlsx"'  
        return response  
      
    def get_queryset(self, request):  
        """基础权限过滤"""  
        qs = super().get_queryset(request)  
          
        if request.user.is_superuser:  
            return qs  
          
        # 普通用户只能看到自己创建的或公共的数据  
        return qs.filter(  
            Q(created_by=request.user) |  
            Q(created_by__isnull=True) |  
            Q(created_by=1)  
        )  
      
    def changelist_view(self, request, extra_context=None):  
        """重写列表视图，添加购物车信息"""  
        extra_context = extra_context or {}  
          
        # 添加购物车信息到上下文  
        cart_items = request.session.get('material_cart', [])  
        extra_context['cart_count'] = len(cart_items)  
          
        return super().changelist_view(request, extra_context)  
      
    def save_model(self, request, obj, form, change):  
        """保存模型时自动设置创建人和更新人"""  
        if not obj.pk:  # 新建时设置创建人  
            obj.created_by = request.user  
        obj.updated_by = request.user  # 更新时设置更新人  
        super().save_model(request, obj, form, change)  
      
    # 权限控制  
    def has_add_permission(self, request):  
        return request.user.is_superuser  
      
    def has_change_permission(self, request, obj=None):  
        if request.user.is_superuser:  
            return True  
        if obj and obj.created_by == request.user:  
            return True  
        return False  
      
    def has_delete_permission(self, request, obj=None):  
        return request.user.is_superuser
        
# 产品信息管理类  
@admin.register(ProductInfo)  
class ProductInfoAdmin(AjaxAdmin):  
    list_display = ('product_code', 'product_name', 'price', 'created_at')  
    search_fields = ('product_code', 'product_name')  
    list_filter = ('created_at',)  
      
    def get_queryset(self, request):  
        qs = super().get_queryset(request)  
        if not request.user.is_superuser:  
            return qs.filter(created_by=request.user)  
        return qs